<?php

/**
 * 后台网址设置
 * @author  xiaobai
 * @date    2017-01-08
 */

namespace app\panel\controller;

use think\Controller;
use think\Request;
use think\Image;

class Uploads extends Controller
{
    private static $uploadFileTypes = [
        'baseImage'  => 'png,jpg,jpeg,gif',
        'jpgImage'   => 'jpg,jpeg',
        'package'    => 'zip,rar',
        'officeFile' => 'doc,xls,ppt,docx,xlsx,pptx,csv',
        'wordFile'   => 'doc,docx',
        'excelFile'  => 'xls,xlsx,csv',
        'pptFile'    => 'ppt,pptx',
        'pdfFile'    => 'pdf',
        'txtFile'    => 'txt',
    ];

    /**
     * 上传文件，支持图片、压缩包、文档等
     * @return array
     */
    public function uploadFile()
    {
        if ($this->request->isPost()) {
            // 判断访问权限
            $timestamp    = input('post.timestamp');
            $token        = input('post.token');
            $quality      = input('post.quality');                    // 压缩质量，100为最高
            $size         = input('post.size', 0, 'intval');          // 上传文件大小
            $fileExt      = input('post.fileExt');                    // 支持上传文件格式
            $img_width    = input('post.img_width', 0, 'intval');     // 压缩图片宽度，目前只支持等比例压缩
            $img_height   = input('post.img_height', 0, 'intval');    // 压缩图片高度
            $thumb_width  = input('post.thumb_width', 0, 'intval');   // 缩略图宽度  
            $thumb_height = input('post.thumb_height', 0, 'intval');  // 缩略图高度
            $thumb_type   = input('post.thumb_type', 0, 'intval');    // 生成缩略图类型: 1等比例; 2生成后填充; 3局中裁剪; 4左上角; 5右下角; 6固定尺寸

            // 基础图片后缀
            $imageTypes = self::$uploadFileTypes['baseImage'];
            $imageTypes = explode(',', $imageTypes);

            $verifyToken = md5('upload_self' . $timestamp);
            if ($token != $verifyToken) {
                $res['status'] = 0;
                $res['msg']    = '参数不对，操作错误！';
                return json($res);
            }
            // 验证文件格式
            $ret = $this->_getFileExt($fileExt);
            if ($ret['code'] == 1) {
                return json(['status'=>0, 'msg'=>$ret['msg']]);
            }
            $file_types = $ret['data'];

            $id = date('is',time()) . mt_rand(1000,9999);
            // 接收删除参数
            $upFile = $this->request->file('file');
 
            // 计算md5和sha1散列值，作用避免文件重复上传
            $md5  = $upFile->hash('md5');
            $sha1 = $upFile->hash('sha1');

            // 移动到上传文件目录下
            $filePath = ROOT_PATH . 'public/uploads/' . date('Y');
            $size     = !empty($size) ? $size : 2;
            $size     = $size * 1024 * 1024;         // 最大上传大小，默认为2MB，单位为字节
            $info     = $upFile->validate(['size'=>$size, 'ext'=>$file_types])->move($filePath);
            if (!$info) {
                return json(['status'=>0, 'msg'=>$upFile->getError()]);
            }
            $file_info = $info->getInfo();                  // 获取上传文件的基本信息
            $file_ext  = strtolower($info->getExtension()); // 上传文件的后缀
            $save_path = '/uploads/' . date('Y') . '/';     // 保存路径

            // 上传文件为图片时处理
            if (in_array($file_ext, $imageTypes)) {
                $fullFilePath = $filePath . '/' . $info->getSaveName();
                $image        = Image::open($fullFilePath);
                // 压缩图片质量
                if (!empty($quality) && (empty($img_width) || empty($img_height))) {
                    $image->save($fullFilePath, null, $quality);    // 压缩图片质量
                } elseif (empty($quality) && (!empty($img_width) || !empty($img_height))) {
                    $image->thumb($img_width, $img_height)->save($fullFilePath);
                } elseif (!empty($quality) && (!empty($img_width) || !empty($img_height))) {
                    $image->thumb($img_width, $img_height)->save($fullFilePath,  null, $quality);
                }
                // 生成缩略图
                if (!empty($thumb_width) && !empty($thumb_height) && !empty($thumb_type)) {
                    $img_infos  = explode('.', $info->getFileName());
                    $thumb_name = $img_infos[0] . '_thumb.' . $info->getExtension();

                    $image->thumb($thumb_width, $thumb_height, $thumb_type)->save($filePath . '/' . date('Ymd') . '/' . $thumb_name, null, 85);
                }
                // 设置水印
                if (!empty(config('other.watermark'))) {
                    $watermark = config('other.watermark');
                    if ($watermark['type'] == 'text') {
                        $text = iconv("GB2312", "UTF-8", $watermark['text']);
                        $image->text($text, $watermark['font'], $watermark['size'], $watermark['color'], $watermark['locate'], $watermark['offset'])->save($fullFilePath);
                    }
                }

                // 同步写入云存储
                $yun_file_path = $this->_setYunData($fullFilePath, $info->getSaveName(), $save_path);
            }

            // 返回文件信息
            $data['id']   = $id;
            $data['url']  = !empty($yun_file_path) ? $yun_file_path : $save_path . str_replace('\\', '/', $info->getSaveName());
            $data['name'] = $file_info['name'];
            $data['size'] = $this->sizeformat($file_info['size']);

            // 上传文件的图片显示，如果是图片直接使用，其他文件获取
            if (in_array($file_ext, $imageTypes)) {
                $data['img_url'] = $data['url'];
            } else {
                $data['img_url'] = $this->_getFileExtIcon($file_ext);
            }

            $res['status'] = 1;
            $res['msg']    = '上传成功';
            $res['data']   = $data;
            return json($res);
        } else {
            return ['status'=>0, 'msg'=>'非法请求!'];
        }
    }

    /**
     * 把字节转换成多少KB、MB、GB、TB等单位的数据
     * @param $bytesize     [字节大小]
     * @return string
     */
    private function sizeformat($bytesize)
    {
        $i = 0;
        //当$bytesize 大于是1024字节时，开始循环，当循环到第4次时跳出；
        while (abs($bytesize)>=1024) {
            $bytesize = $bytesize/1024;
            $i++;
            if($i==4)break;
        }

        //将Bytes,KB,MB,GB,TB定义成一维数组；
        $units   = array("Bytes","KB","MB","GB","TB");
        $newsize = round($bytesize,2);
        return("$newsize $units[$i]");
    }

    /**
     * ajax plupload 上传图片框
     */
    public function ajaxPlupload()
    {
        $args     = input('param.args');
        $file_arr = explode(',', $args);
        $limit    = intval($file_arr[0]) ? intval($file_arr[0]) : 1;    // 上传文件个数

        // 上传文件支持格式
        $res = $this->_getFileExt($file_arr[1]);
        if ($res['code'] == 1) {
            $this->error($res['msg']);
        }
        $file_types = $res['data'];

        // 上传文件大小限制
        $file_size = !empty($file_arr[2]) ? $file_arr[2] : '2';

        // 上传图片要求
        // 压缩图片(压缩质量-压缩后的最大宽高-等比例)
        if (!empty($file_arr[3])) {
            $resize_arr     = explode('|', $file_arr[3]);
            $resize_quality = $resize_arr[0];
            $image_width    = !empty($resize_arr[1]) ? $resize_arr[1] : 0;              // 0为不修改宽度，使用原始宽度
            $image_height   = !empty($resize_arr[2]) ? $resize_arr[2] : $image_width;
            
            $this->assign('resize_quality', $resize_quality);
            $this->assign('image_width', $image_width);
            $this->assign('image_height', $image_height);
        }

        // 生成缩略图(宽高-等比例还是非等比例)
        // 生成缩略图类型: 1等比例; 2生成后填充; 3局中裁剪; 4左上角; 5右下角; 6固定尺寸
        if (!empty($file_arr[4])) {
            $thumb_arr    = explode('|', $file_arr[4]);
            $thumb_width  = $thumb_arr[0];
            $thumb_height = !empty($thumb_arr[1]) ? $thumb_arr[1] : $thumb_width;
            $thumb_type   = !empty($thumb_arr[2]) ? $thumb_arr[2] : 1;

            $this->assign('thumb_width', $thumb_width);
            $this->assign('thumb_height', $thumb_height);
            $this->assign('thumb_type', $thumb_type);
        }

        $this->assign('file_types', $file_types);
        $this->assign('limit', $limit);
        $this->assign('fileExt', $file_arr[1]);
        $this->assign('file_size', $file_size);

        // 使用指定模板的布局功能
        $this->view->engine->layout('alert_layout');
        return $this->fetch();
    }

    /**
     * 获取文件后缀信息
     * @param  string $ext_type 上传文件的别名集
     * @return array
     */
    private function _getFileExt($ext_type = '')
    {
        if (empty($ext_type)) {
            return ['code'=>1, 'msg'=>'请选择上传文件格式'];
        }

        $ext_type = explode('|', $ext_type);
        $ext_arr  = [];
        foreach ($ext_type as $ext) {
            $uploadFileTypes = self::$uploadFileTypes;
            if (!empty($uploadFileTypes[$ext])) {
                $ext_arr[] = $uploadFileTypes[$ext];
            }
        }
        if (empty($ext_arr) || count($ext_arr) <= 0) {
            return ['code'=>1, 'msg'=>'请选择上传文件格式'];
        }
        $file_types = join(',', $ext_arr);

        return ['code'=>0, 'data'=>$file_types];
    }

    /**
     * 获取非图片类型的后缀显示图片地址
     * @param  string $file_ext     文件后缀
     * @return string
     */
    private function _getFileExtIcon($file_ext = '')
    {
        $img_path = '/static/images';
        switch ($file_ext) {
            case 'zip':
                $icon_url = $img_path . '/icon/zip.png';
                break;

            case 'rar':
                $icon_url = $img_path . '/icon/rar.png';
                break;

            case 'doc':
            case 'docx':
                $icon_url = $img_path . '/icon/word.png';
                break;

            case 'xls':
            case 'xlsx':
                $icon_url = $img_path . '/icon/excel.png';
                break;

            case 'ppt':
            case 'pptx':
                $icon_url = $img_path . '/icon/ppt.png';
                break;
            
            case 'csv':
                $icon_url = $img_path . '/icon/csv.png';
                break;

            case 'pdf':
                $icon_url = $img_path . '/icon/pdf.png';
                break;

            case 'txt':
                $icon_url = $img_path . '/icon/txt.png';
                break;

            default:
                $icon_url = $img_path . '/icon/file.png';
                break;
        }

        return $icon_url;
    }

    /**
     * 同步保存到第三方存储平台
     * @param string $full_file_path    本地完整路径
     * @param string $save_name         保存文件名，带后缀
     * @param string $save_file_path    云平台存储路径
     */
    private function _setYunData($full_file_path = '', $save_name = '', $save_file_path = '')
    {
        if (!empty($full_file_path)) {
            $yun_storage = config('other.yun_storage');
            // 同步到又拍云
            if ($yun_storage === 'upyun') {
                $upaiyun    = new \service\Upaiyun();
                $upyun_path = $upaiyun->uploadUpyun($full_file_path, $save_name, $save_file_path);
                $local_path = $save_file_path . str_replace('\\', '/', $save_name);
                $data = [
                    'provider'    => 1,
                    'local_path'  => $local_path,
                    'file_url'    => $upyun_path,
                    'create_time' => date('Y-m-d H:i:s'),
                ];
                @db('local_yun')->insert($data);

                return config('other.upyun.cdn_domain') . $upyun_path;
            }
        }
    }
}
